<template>
  <div class="xmind-context-menu" :style="style">
    <ul>
      <li
        @click="contextMenuClick(item)"
        v-for="(item, index) in contextMenus"
        :key="index"
        :class="{
          'x_disabled': item.disabled,
          'x_warning': item.warning,
          'x_border': item.border,
          'has-child': item.children?.length
        }">
          <p>
            {{ item.name }}
            <span>{{ item.shortKey }}</span>
            <i v-if="item.children?.length" class="ri-arrow-right-s-fill"></i>
          </p>
          <ul
            class="ul-item-children"
            v-if="item.children?.length"
            :style="style.childStyle">
            <li
              @click="contextMenuClick(itemName)"
              v-for="(itemName, idx) in item.children"
              :key="idx"
              :class="{
                'x_disabled': itemName.disabled,
                'x_warning': itemName.warning,
              }">
              <p>
                {{ itemName.name }}
                <span>{{ itemName.shortKey }}</span>
                <i class="ri-check-line"
                  v-if="itemName.operate === 'insert-serial' &&
                    node?.data['child-serial'] === itemName.key"></i>
              </p>
            </li>
          </ul>
        </li>
    </ul>
  </div>
</template>

<script setup>
import { ref, defineProps, defineEmits, computed, watch, onMounted, nextTick } from 'vue'
import serialNumberList from '../config/serialNumber'

const emits = defineEmits(['context-click'])
const props = defineProps({
  type: String,
  node: {
    type: Object,
    default: () => {
      return {}
    }
  },
  batchNodes: {
    type: Array,
    default: () => []
  },
  copyNode: {
    type: Object,
    default: () => null
  },
  copyStyle: {
    type: Object,
    default: () => null
  },
  sourceEvent: {
    type: Object,
    default: () => {
      return {}
    }
  },
  relationStyle: {
    type: Object,
    default: () => null
  },
  copyRelationStyle: {
    type: Object,
    default: () => null
  },
  summaryStyle: {
    type: Object,
    default: () => null
  },
  copySummaryStyle: {
    type: Object,
    default: () => null
  }
})
const style = ref({})
const [windowWidth, windowHeight] = [ref(0), ref(0)]
const contextMenus = computed(() => {
  // 右键关系连线操作
  if (props.relationStyle || props.summaryStyle) {
    const type = props.relationStyle ? 'relation' : 'summary'
    return [
      {
        name: '拷贝样式',
        operate: `copy-${type}-style`
      },
      {
        name: '引用样式',
        operate: `past-${type}-style`,
        disabled: props.relationStyle ? !props.copyRelationStyle : !props.copySummaryStyle
      },
      {
        name: '重置样式',
        operate: `reset-${type}-style`,
        border: true
      },
      {
        name: '删除',
        operate: `delete-${type}`,
        shortKey: 'DELETE',
        warning: true
      }
    ]
  }
  if (props.type === 'single') {
    // 单个主题右键操作
    return [
      {
        name: '插入',
        children: [
          {
            name: '标记',
            operate: 'insert-marker'
          },
          {
            name: '图片',
            operate: 'insert-tupian'
          },
          {
            name: '标签',
            operate: 'insert-tag'
          },
          {
            name: '备注',
            operate: 'insert-beizhu'
          },
          {
            name: '超链接',
            operate: 'insert-link'
          },
          {
            name: '画布主题锚点',
            operate: 'insert-topiclink'
          },
          {
            name: '方程式',
            operate: 'insert-latex'
          },
          {
            name: '同级主题',
            disabled: !props.node?.parent,
            operate: 'insert-brother',
            shortKey: 'Enter'
          },
          {
            name: '子主题',
            disabled: false,
            operate: 'insert-child',
            shortKey: 'Tab'
          }
        ]
      },
      {
        name: '设为任务',
        disabled: !props.node?.parent || props.node?.data.isTask,
        operate: 'insert-task'
      },
      {
        name: '取消任务',
        disabled: !props.node?.data.isTask,
        operate: 'delete-element',
        key: 'isTask'
      },
      {
        name: '编号子节点',
        children: serialNumberList,
        border: true
      },
      {
        name: '删除',
        warning: true,
        children: [
          {
            name: '图片',
            disabled: !props.node?.data.imageInfo,
            operate: 'delete-element',
            warning: true,
            key: 'imageInfo'
          },
          {
            name: '超链接',
            disabled: !props.node?.data.link,
            operate: 'delete-element',
            warning: true,
            key: 'link'
          },
          {
            name: '画布主题锚点',
            disabled: !props.node?.data.topiclink,
            operate: 'delete-element',
            warning: true,
            key: 'topiclink'
          },
          {
            name: '标签',
            disabled: !props.node?.data.tag,
            operate: 'delete-element',
            warning: true,
            key: 'tag'
          },
          {
            name: '备注',
            disabled: !props.node?.data.comment,
            operate: 'delete-element',
            warning: true,
            key: 'comment'
          },
          {
            name: '方程式',
            disabled: !props.node?.data.latex,
            operate: 'delete-element',
            warning: true,
            key: 'latex'
          },
          {
            name: '主题',
            disabled: props.node?.data.isRoot,
            operate: 'delete',
            warning: true,
            shortKey: 'Delete'
          }
        ]
      },
      {
        name: '仅删除当前主题',
        disabled: props.node?.data.isRoot,
        warning: true,
        border: true,
        operate: 'delete',
        key: 'only-self'
      },
      {
        name: '上移主题',
        disabled: !props.node?.parent,
        operate: 'up',
        shortKey: 'Ctrl + ↑'
      },
      {
        name: '下移主题',
        disabled: !props.node?.parent,
        operate: 'down',
        shortKey: 'Ctrl + ↓',
        border: true
      },
      {
        name: '复制主题',
        disabled: false,
        operate: 'copy',
        shortKey: 'Ctrl + C'
      },
      {
        name: '剪切主题',
        disabled: !props.node?.parent,
        operate: 'cut',
        shortKey: 'Ctrl + X'
      },
      {
        name: '粘贴主题',
        disabled: !props.copyNode,
        operate: 'past',
        shortKey: 'Ctrl + V',
        border: true
      },
      {
        name: '复制样式',
        disabled: false,
        operate: 'copy-style',
        shortKey: 'Ctrl + Shift + C'
      },
      {
        name: '引用样式',
        disabled: !props.copyStyle,
        operate: 'reference-style',
        shortKey: 'Ctrl + Shift + V',
        border: true
      },
      {
        name: '清除自定义样式',
        disabled: false,
        operate: 'reset-style',
        shortKey: 'Ctrl + Alt + 0'
      }
    ]
  } else {
    // 批量主题右键操作
    return [
      {
        name: '新增自由主题',
        operate: 'insert-independent',
        shortKey: 'Dbclick'
      },
      {
        name: '插入',
        children: [
          {
            name: '同级主题',
            disabled: !props.batchNodes.length,
            operate: 'insert-brother',
            shortKey: 'Enter'
          },
          {
            name: '子主题',
            disabled: !props.batchNodes.length,
            operate: 'insert-child',
            shortKey: 'Tab'
          }
        ]
      },
      {
        name: '删除',
        warning: true,
        children: [
          {
            name: '图片',
            disabled: !props.batchNodes.length,
            operate: 'delete-element',
            warning: true,
            key: 'imageInfo'
          },
          {
            name: '超链接',
            disabled: !props.batchNodes.length,
            operate: 'delete-element',
            warning: true,
            key: 'link'
          },
          {
            name: '标签',
            disabled: !props.batchNodes.length,
            operate: 'delete-element',
            warning: true,
            key: 'tag'
          },
          {
            name: '备注',
            disabled: !props.batchNodes.length,
            operate: 'delete-element',
            warning: true,
            key: 'comment'
          },
          {
            name: '主题',
            disabled: !props.batchNodes.length,
            operate: 'delete',
            warning: true,
            shortKey: 'Delete'
          }
        ],
        border: true
      },
      {
        name: '引用样式',
        disabled: !props.batchNodes.length || !props.copyStyle,
        operate: 'reference-style',
        shortKey: 'Ctrl + Shift + V'
      },
      {
        name: '清除自定义样式',
        disabled: !props.batchNodes.length,
        operate: 'reset-style',
        border: true,
        shortKey: 'Ctrl + Alt + 0'
      },
      {
        name: '收起所有',
        disabled: false,
        operate: 'noexpand-all'
      },
      {
        name: '展开所有',
        disabled: false,
        operate: 'expand-all'
      },
      {
        name: '定位到根节点',
        disbaled: false,
        operate: 'map-center',
        shortKey: 'Ctrl + R'
      }
    ]
  }
})

function contextMenuClick (menuItem) {
  if (menuItem.disabled || menuItem.children?.length) return
  emits('context-click', menuItem.operate, props.type, menuItem.key)
}

onMounted(() => {
  windowWidth.value = document.body.clientWidth
  windowHeight.value = document.body.clientHeight
})

watch(() => props.sourceEvent, newVal => {
  if (newVal) {
    nextTick(() => {
      const childWidth = 200
      const { pageX, pageY } = props.sourceEvent
      const { width, height } = document.querySelector('.xmind-context-menu').getBoundingClientRect()
      const top = Math.min(pageY, windowHeight.value - height - 20)
      const left = Math.min(pageX, windowWidth.value - width - 20)
      const childTranslateX = (left + width + childWidth > windowWidth.value ? -childWidth - 5 : width + 5) + 'px'
      style.value = {
        top: `${top}px`,
        left: `${left}px`,
        childStyle: {
          transform: `translate(${childTranslateX}, 0)`
        }
      }
    })
  }
})
</script>

<style lang="scss" scoped>
.xmind-context-menu {
  position: fixed;
  z-index: 999;
  box-shadow: 0px 8px 24px rgba(25,25,26,.06), 0px 4px 16px rgba(25,25,26,.04), 0px 0px 4px rgba(25,25,26,.04);
  padding: 4px 0;
  border-radius: 8px;
  background: #fff;
  border: 1px solid rgba(18,17,42,.07);
  ul {
    position: relative;
    &::after {
      content: "";
      left: -8px;
      right: -8px;
      position: absolute;
      top: -10px;
      bottom: -10px;
      background: transparent;
      z-index: 1;
    }
    li {
      width: 230px;
      position: relative;
      user-select: none;
      padding: 4px 15px;
      margin: 8px 0;
      z-index: 9;
      p {
        height: 100%;
        white-space: nowrap;
        color: #27292A;
        font-size: 12px;

        padding: 2px 6px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        span {
          color: #949699;
          font-size: 11px;
          opacity: .9;
        }
        .ri-arrow-right-s-fill {
          font-size: 16px;
          color: #27292A;
        }
      }
      &:hover {
        background: #f5f5f5;
        .ul-item-children {
          display: block;
        }
      }
      &.x_warning {
        p {
          color: #af2c2c;
        }
      }
      &.x_disabled {
        pointer-events: none;
        span, p {
          color: rgba(0, 0, 0, 0.1);
        }
      }
      &.x_border {
        position: relative;
        margin-bottom: 12px;
        &::before {
          content: "";
          position: absolute;
          left: 12px;
          right: 12px;
          bottom: -7px;
          height: 1px;
          background-color: #f5f5f5;
        }
      }
    }
    &.ul-item-children {
      position: absolute;
      left: 0;
      top: 0;
      box-shadow: 0px 8px 24px rgba(25,25,26,.06), 0px 4px 16px rgba(25,25,26,.04), 0px 0px 4px rgba(25,25,26,.04);
      padding: 2px 0;
      border-radius: 6px;
      background: #fff;
      display: none;
      li {
        height: 28px;
        width: 200px;
        position: relative;
        .ri-check-line {
          position: absolute;
          right: 10px;
          top: 8px;
          font-size: 16px;
          color: #999;
        }
      }
    }
  }
}
</style>
